"""
Python字典(dict)

字典是Python中的可变映射类型，以键值对(key-value pair)形式存储数据。
字典使用花括号{}表示，键和值之间使用冒号:分隔，不同键值对之间使用逗号,分隔。
字典的键必须是不可变的数据类型(如字符串、数字、元组)，而值可以是任意数据类型。
"""

# =============== 1. 字典的创建 ===============

print("="*50)
print("1. 字典的创建")
print("="*50)

# 创建空字典的两种方式
empty_dict1 = {}
empty_dict2 = dict()
print(f"空字典1: {empty_dict1}")
print(f"空字典2: {empty_dict2}")

# 创建包含键值对的字典，最常用的创建字典的方式
student = {
    "name": "张三",
    "age": 20,
    "score": 95,
    "is_male": True
}
print(f"学生信息: {student}")

# 使用dict()构造函数创建字典的几种方式。不常见，了解即可。
# 1. 使用关键字参数
person = dict(name="李四", age=25, city="上海")
print(f"使用关键字参数创建: {person}")

# 2. 使用二元组列表
colors = dict([("red", "#FF0000"), ("green", "#00FF00"), ("blue", "#0000FF")])
print(f"使用二元组列表创建: {colors}")

# 3. 使用zip()函数将两个列表合并为字典
keys = ["a", "b", "c"]
values = [1, 2, 3]
letter_dict = dict(zip(keys, values))
print(f"使用zip()创建: {letter_dict}")

# 字典推导式
squares = {x: x*x for x in range(1, 6)}
print(f"使用字典推导式创建: {squares}")


# =============== 2. 访问字典中的值 ===============

print("\n"+"="*50)
print("2. 访问字典中的值")
print("="*50)

# 创建一个示例字典
user = {
    "id": 1001,
    "username": "user123",
    "email": "user@example.com",
    "is_active": True,
    "level": 3
}
print(f"用户字典: {user}")

# 方式一：使用方括号访问法 - 如果键不存在会引发KeyError
print(f"用户名: {user['username']}")
print(f"邮箱: {user['email']}")

# 尝试访问不存在的键会引发错误
try:
    print(user['phone'])  # 'phone'键不存在
except KeyError as e:
    print(f"错误信息: {e}")

# 方式二：使用get()方法访问 - 如果键不存在返回None或指定的默认值
# 推荐使用get()方法，因为如果键不存在不会引发错误，而是返回None或指定的默认值，一定要记住这种方法！
print(f"用户等级: {user.get('level')}")
print(f"电话号码: {user.get('phone')}")  # 返回None
print(f"手机号码: {user.get('mobile', '未设置')}")  # 返回默认值'未设置'

# get()方法不会修改原字典，只是返回一个值


# =============== 3. 修改、添加和删除键值对 ===============

print("\n"+"="*50)
print("3. 修改、添加和删除键值对")
print("="*50)

# 创建一个示例字典
product = {
    "id": "P001",
    "name": "笔记本电脑",
    "price": 5999,
    "in_stock": True
}
print(f"原始商品信息: {product}")

# 修改已有键的值
product["price"] = 6299
print(f"修改价格后: {product}")

# 添加新的键值对
# 跟修改的方法是一样的，因此记住，如果键存在，则修改，如果键不存在，则添加。
product["brand"] = "华硕"
product["color"] = "银色"
print(f"添加品牌和颜色后: {product}")

# 删除键值对的几种方法
# 1. 使用del语句
del product["color"]
print(f"删除颜色后: {product}")

# 2. 使用pop()方法 - 返回被删除的值
removed_price = product.pop("price")
print(f"移除的价格: {removed_price}")
print(f"移除价格后: {product}")

# 3. 使用popitem()方法 - 移除并返回最后添加的键值对
last_item = product.popitem()  # 返回一个元组(key, value)
print(f"移除的最后一项: {last_item}")
print(f"移除最后一项后: {product}")

# 4. 使用clear()方法清空字典
product.clear()
print(f"清空后的商品字典: {product}")


# =============== 4. 字典的遍历 ===============

print("\n"+"="*50)
print("4. 字典的遍历")
print("="*50)

# 创建一个示例字典
scores = {
    "语文": 85,
    "数学": 92,
    "英语": 78,
    "物理": 90,
    "化学": 88
}
print(f"学科成绩: {scores}")

# 1. 遍历字典的键
print("\n遍历键:")
for subject in scores:
    print(subject)

# 等价于使用keys()方法，更明确清晰易读
print("\n使用keys()遍历键:")
for subject in scores.keys():
    print(subject)

# 2. 遍历字典的值
print("\n遍历值:")
for score in scores.values():
    print(score)

# 3. 同时遍历键和值
print("\n同时遍历键和值:")
for subject, score in scores.items():
    print(f"{subject}: {score}")

# 4. 带索引的遍历
print("\n带索引的遍历:")
for i, (subject, score) in enumerate(scores.items()):
    print(f"{i+1}. {subject}: {score}")


# =============== 5. 字典长度 ===============

print("\n"+"="*50)
print("5. 字典长度")
print("="*50)

# 创建几个示例字典
dict1 = {"a": 1, "b": 2, "c": 3}
dict2 = {}
dict3 = {"name": "张三", "scores": {"语文": 85, "数学": 92}}

# 使用len()函数获取字典的长度（键值对数量）
print(f"dict1的长度: {len(dict1)}")
print(f"空字典的长度: {len(dict2)}")
print(f"dict3的长度: {len(dict3)}")  # 注意：嵌套字典被视为一个值


# =============== 6. 检查键是否存在 ===============

print("\n"+"="*50)
print("6. 检查键是否存在")
print("="*50)

# 创建一个示例字典
settings = {
    "theme": "dark",
    "font_size": 14,
    "notifications": True,
    "language": "zh-CN"
}
print(f"设置: {settings}")

# 使用in运算符检查键是否存在
print(f"'theme'键是否存在: {'theme' in settings}")
print(f"'volume'键是否存在: {'volume' in settings}")

# 使用not in运算符检查键是否不存在
print(f"'volume'键是否不存在: {'volume' not in settings}")

# 在条件语句中使用
if "notifications" in settings:
    print(f"通知设置: {'开启' if settings['notifications'] else '关闭'}")

if "auto_save" not in settings:
    print("自动保存功能未设置")


# =============== 7. 实际应用例子：AI对话参数 ===============

print("\n"+"="*50)
print("7. 实际应用例子：AI对话参数")
print("="*50)

def generate_ai_response(prompt, **kwargs):
    """
    模拟AI生成响应的函数
    
    参数:
    - prompt: 提示词
    - kwargs: 其他配置参数
    """
    # 默认参数
    default_params = {
        "model": "gpt-3.5-turbo",
        "temperature": 0.7,  # 控制创造性（0-1）
        "max_tokens": 150,   # 最大输出长度
        "stream": False,     # 是否流式输出
        "presence_penalty": 0.0,  # 主题重复度惩罚
        "frequency_penalty": 0.0  # 词汇重复度惩罚
    }
    
    # 使用用户提供的参数更新默认参数
    # update()方法用于合并两个字典，重复的键会被更新
    params = default_params.copy()
    params.update(kwargs)
    
    # 打印出请求参数
    print("AI请求参数:")
    for key, value in params.items():
        print(f"  {key}: {value}")
    
    # 模拟AI响应
    model_type = "流式" if params["stream"] else "非流式"
    creativity = "高创造性" if params["temperature"] > 0.5 else "低创造性"
    
    print(f"\n模拟{model_type}响应（使用{params['model']}模型，{creativity}输出）:")
    return f"这是对'{prompt}'的回答，最大长度{params['max_tokens']}tokens。\n"

# 示例1：使用默认参数
response1 = generate_ai_response("你好，请介绍一下自己")
print(response1)

# 示例2：自定义部分参数
custom_params = {
    "model": "gpt-4",
    "temperature": 0.9,
    "max_tokens": 500,
    "stream": True
}

response2 = generate_ai_response(
    "请写一首关于人工智能的诗",
    **custom_params  # 使用**运算符解包字典作为关键字参数
)
print(response2)

# 示例3：动态构建参数
def get_user_ai_settings():
    """模拟从用户配置中获取AI设置"""
    return {
        "model": "deepseek-chat",
        "temperature": 0.5,
        "stream": True
    }

user_settings = get_user_ai_settings()
# 可以在传递前修改字典
if user_settings["temperature"] < 0.6:
    user_settings["max_tokens"] = 300

response3 = generate_ai_response("解释量子物理学基础概念", **user_settings)
print(response3)

print("\n字典学习结束！字典是Python中最常用的数据结构之一，尤其适合表示有关联的数据集合。") 